package charpter01_basic.lession05_impl_producter_consumer.my_queue;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * await() 和 wait() 的区别
 * wai()是Object类提供的，一般与synchronized联合使用。调用wait之后会释放锁，导致线程等待。唤醒进程使用notify()或者notifyAll()
 * await()Condition类是当中的，一般与Lock联合使用, 唤醒线程使用 signal() 或者 signalAll()。
 */
public class MyBlockingQueueForCondition {
    private final LinkedList<Integer> queue;
    private final int max;
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notEmpty = lock.newCondition();
    private final Condition notFull = lock.newCondition();

    public MyBlockingQueueForCondition(int size) {
        this.max = size;
        this.queue = new LinkedList<>();
    }

    public void put(Integer i) throws InterruptedException {
        lock.lock();
        try {
            while (queue.size() == max) {
                // 这里注意应该调用 condition 的 await 方法
                notFull.await();
            }
            queue.add(i);
            notEmpty.signalAll();
        } finally {
            lock.unlock();
        }

    }

    public Integer take() throws InterruptedException {
        lock.lock();
        try {
            while (queue.size() == 0) {
                // 这里注意应该调用 condition 的 await 方法
                notEmpty.await();
            }
            Integer remove = queue.remove();
            notFull.signalAll();
            return remove;
        } finally {
            lock.unlock();
        }
    }

    public int size(){
        return queue.size();
    }

}